import os
import pytz
import time
import shutil
import logging
from glob import glob
from datetime import datetime, timedelta
import pandas as pd

MY_DEBUG_LEVEL = 15  # between DEBUG(10) and INFO(20)

DEFAULT_TZ = pytz.timezone('hongkong')

def now_time():
    return datetime.now(DEFAULT_TZ)

def wait_until_ready(mgr, symbol, run_time, expire_time):
    while not mgr.check_ready(symbol, run_time):
        time.sleep(0.01)
        if now_time() > expire_time:
            return False

    return True

class CandleFeatherManager:

    def __init__(self, base_dir):
        '''
        初始化，设定读写根目录
        '''
        self.base_dir = base_dir

    def format_ready_file_path(self, symbol, run_time):
        '''
        获取 ready file 文件路径, ready file 为每周期 K线文件锁
        ready file 文件名形如 {symbol}_{runtime年月日}_{runtime_时分秒}.ready
        '''
        run_time_str = run_time.strftime('%Y%m%d_%H%M%S')
        name = f'{symbol}_{run_time_str}.ready'
        file_path = os.path.join(self.base_dir, name)
        return file_path

    def check_ready(self, symbol, run_time):
        '''
        检查 symbol 对应的 ready file 是否存在，如存在，则表示 run_time 周期 K线已获取并写入 Feather
        '''
        ready_file_path = self.format_ready_file_path(symbol, run_time)
        return os.path.exists(ready_file_path)

    def read_candle(self, symbol) -> pd.DataFrame:
        '''
        读取 symbol 对应的 K线
        '''
        return pd.read_feather(os.path.join(self.base_dir, f'{symbol}.fea'))

def fetch_swap_candle_data_BMAC(candle_mgr: CandleFeatherManager, symbol_list, run_time, expire_sec, min_candle_num):
    unready_symbols = set(symbol_list)
    expire_time = run_time + timedelta(seconds=expire_sec)
    symbol_data = dict()

    while True:
        while len(unready_symbols) > 0:
            readies = {s for s in unready_symbols if candle_mgr.check_ready(s, run_time)}
            if len(readies) == 0:
                break
            for sym in readies:
                df = candle_mgr.read_candle(sym)
                if len(df) < min_candle_num:
                    print('no enough data', sym)
                    continue
                df['symbol'] = sym
                symbol_data[sym] = df
            unready_symbols -= readies
            logging.log(MY_DEBUG_LEVEL, 'readys=%d, unready=%d, read=%d', len(readies), len(unready_symbols),
                        len(symbol_data))
        if len(unready_symbols) == 0:
            break
        if now_time() > expire_time:
            break
        time.sleep(0.01)

    return symbol_data

def fetch_all_binance_swap_candle_data2(quant, symbol_list, run_time):
    # 时区转化
    if run_time.tzinfo == None:
        run_time = run_time.replace(tzinfo=DEFAULT_TZ)
    print(run_time)

    # 从 BMAC 读取合约数据
    expire_time = run_time + timedelta(seconds=quant.bmac_expire_sec)
    is_ready = wait_until_ready(quant.exg_mgr, 'exginfo', run_time, expire_time)

    if not is_ready:
        raise RuntimeError(f'exginfo not ready at {now_time()}')

    symbol_candle_data = fetch_swap_candle_data_BMAC(quant.candle_mgr, symbol_list, run_time, quant.bmac_expire_sec, quant.min_candle_num)

    return symbol_candle_data


# class QuantConfig:

#     def __init__(self, cfg):
#         self.interval = cfg['interval']

#         self.bmac_dir = cfg['bmac_dir']
#         self.bmac_expire_sec = cfg['bmac_expire_sec']

#         self.min_candle_num = cfg['min_candle_num']

#         self.exg_mgr = CandleFeatherManager(os.path.join(self.bmac_dir, f'exginfo_{self.interval}'))
#         self.candle_mgr = CandleFeatherManager(os.path.join(self.bmac_dir, f'usdt_swap_{self.interval}'))

#         self.debug = cfg.get('debug', False)
        
# def fetch_swap_candle_data_2(run_time):
#     cfg = {
#         'interval': '1h',
#         'bmac_dir': '/home/admin/BMAC中性2/binance_market_async_crawler-master/usdt_1h_alpha',
#         'bmac_expire_sec': 30,
#         'min_candle_num': 999,
#         'debug': False,
#     }

#     Q = QuantConfig(cfg)

#     if run_time.tzinfo == None:
#         run_time = run_time.replace(tzinfo=DEFAULT_TZ)
#     df_exg = load_market(Q.exg_mgr, run_time, Q.bmac_expire_sec)
#     symbol_list = list(df_exg['symbol'])
#     symbol_candle_data = fetch_swap_candle_data_BAMC(Q.candle_mgr, symbol_list, run_time, Q.bmac_expire_sec, Q.min_candle_num)

#     return symbol_candle_data

def get_fundingrate(quant, run_time):
    # 从 BMAC 读取资金费
    expire_time = run_time + timedelta(seconds=quant.bmac_expire_sec)
    is_ready = wait_until_ready(quant.exg_mgr, 'funding', run_time, expire_time)

    if not is_ready:
        raise RuntimeError(f'Funding rate not ready')

    return quant.exg_mgr.read_candle('funding')
